package handler;

import java.util.ArrayList;
import java.util.List;

/**
 * Manipulates a collection of Equation nodes in-memory. This class was produced
 * by refactoring the previous group's code into two separate classes. The
 * code that actually reads/writes XML has been moved into the XMLHandler
 * class, which is wrapped by the various data access object classes.
 */
public class EquationNodeHandler {
    /**
     * Stores the notebook equations that this class manipulates
     */
    private final List<EquateNode> notebookEquations;

    /**
     * Constructs a new EquationNodeHandler
     * @param notebookEquations a collection of notebook equations that this
     * class will manage
     */
    public EquationNodeHandler(List<EquateNode> notebookEquations) {
        this.notebookEquations = notebookEquations;
    }

    /**
     * Returns the current list of notebook equations
     * @return List of notebook equation objects
     */
    public List<EquateNode> getEquations() {
        return this.notebookEquations;
    }
    
    /**
     * Removes the specified equation from the list
     * 
     * @param eqStr the string representing the equation to remove
     * @return boolean true if the equation was removed, false otherwise
     */
    public boolean deleteEquation(final String eqStr) {
        // find equation string in notebookEquations List
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                // delete entire equate node
                notebookEquations.remove(i);
                return true;
            }
        }

        // equation wasn't found to delete
        return false;
    }

    /**
     * Deletes the interval for the specified equation
     * 
     * @param eqStr string representation of the equation for which to remove this interval
     * @param aPt a coordinate
     * @param bPt b coordinate
     * @return boolean true if the interval was removed, false otherwise
     */
    public boolean deleteInterval(final String eqStr, final double aPt, final double bPt) {
        EquateNode eq = null;

        // finding the corresponding EquateNode in List
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                eq = notebookEquations.get(i);
                break;
            }
        }

        if (eq == null) {
            // eqStr does not exist
            return false;
        }

        final ArrayList<IntervalNode> intrvls = eq.getIntervals();
        IntervalNode temp;

        // finding the corresonding IntervalNode in ArrayList
        for (int i = 0; i < intrvls.size(); i++) {
            temp = intrvls.get(i);
            if (aPt == temp.getA() && bPt == temp.getB()) {
                intrvls.remove(i);
                // interval deleted successfully
                return true;
            }
        }

        // interval doesn't exist
        return false;
    }

    /**
     * Deletes the specified tangent point for the specified equation and interval
     * 
     * @param eqStr string representation of the equation
     * @param aPt a coordinate
     * @param bPt b coordinate 
     * @param tanPt tangent point
     * @return boolean true if the tangent point was deleted, false otherwise
     */
    public boolean deletePoint(final String eqStr, final double aPt, final double bPt, final double tanPt) {
        EquateNode eq = null;
        IntervalNode intnd = null;

        // finding the corresonding EquateNode in ArrayList
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                eq = notebookEquations.get(i);
                break;
            }
        }

        if (eq == null) {
            // eqStr does not exist
            return false;
        }

        final ArrayList<IntervalNode> intrvls = eq.getIntervals();
        IntervalNode temp;

        // finding the corresonding IntervalNode in ArrayList
        for (int i = 0; i < intrvls.size(); i++) {
            temp = intrvls.get(i);
            if (aPt == temp.getA() && bPt == temp.getB()) {
                intnd = temp;
                break;
            }
        }

        if (intnd == null) {
            // aPt and bPt do not exist
            return false;
        }

        final ArrayList<Double> tanPts = intnd.getTanPts();

        for (int i = 0; i < tanPts.size(); i++) {
            if (tanPts.get(i).doubleValue() == tanPt) {
                // tangent point deleted
                tanPts.remove(i);
                return true;
            }
        }

        // TODO: should this line be removed?
        tanPts.add(new Double(tanPt));

        // tangent point does not exists
        return false;
    }

    /**
     * Retrieves a list of all equations
     * @return String[] array of equations
     */
    public String[] retrieveEquations() {
        final String[] eq = new String[notebookEquations.size()];

        System.out.println("retrieveEquations() has been called:");

        for (int i = 0; i < notebookEquations.size(); i++) {
            eq[i] = notebookEquations.get(i).getEquation();
            System.out.println("Equation: " + eq[i]);
        }
        return eq;
    }

    /**
     * retrieveIntervalsAsString() - assumes that the equation exists in the
     * file
     * 
     * @param eqStr
     * @return String[]
     */
    public String[] retrieveIntervalsAsString(final String eqStr) {
        String[] in;
        EquateNode eq = null;

        // finding the corresonding EquateNode in ArrayList
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                eq = notebookEquations.get(i);
                break;
            }// if
        }// for(i)

        // eqStr does not exist print an error and return empty array
        if (eq == null) {
            System.err.println("The equation '" + eqStr + "' does not exist in the file");
            return new String[1];
        }// if(null)

        final ArrayList<IntervalNode> intrvl = eq.getIntervals();
        in = new String[intrvl.size()];
        IntervalNode temp;
        int j = 0;

        for (int i = 0; i < intrvl.size(); i++) {
            temp = intrvl.get(i);
            in[j] = temp.getA() + "," + temp.getB();

            j++;
        }// for(i)

        return in;
    }// retrieveIntervalsAsString()

    /**
     * retrievePointsAsString()
     * 
     * @param eqStr
     * @param aPt
     * @param bPt
     * @return String[]
     */
    public String[] retrievePointsAsString(final String eqStr, final double aPt, final double bPt) {
        String[] pts;
        EquateNode eq = null;
        IntervalNode intnd = null;

        // finding the corresonding EquateNode in ArrayList
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                eq = notebookEquations.get(i);
                break;
            }// if
        }// for(i)

        // eqStr does not exist print an error and return empty array
        if (eq == null) {
            System.err.println("The equation '" + eqStr + "' does not exist in the file");
            return new String[1];
        }// if(null)

        final ArrayList<IntervalNode> intrvls = eq.getIntervals();
        IntervalNode temp;

        // finding the corresonding IntervalNode in ArrayList
        for (int i = 0; i < intrvls.size(); i++) {
            temp = intrvls.get(i);
            if (aPt == temp.getA() && bPt == temp.getB()) {
                intnd = temp;
                break;
            }// if
        }// for(i)

        // aPt and bPt do not exist print an error and return empty array
        if (intnd == null) {
            System.err.println("The interval A=" + aPt + " and B=" + bPt + " does not exist in the file");
            return new String[1];
        }// if(null)

        final ArrayList<Double> tanPts = intnd.getTanPts();
        pts = new String[tanPts.size()];

        for (int i = 0; i < tanPts.size(); i++) {
            pts[i] = tanPts.get(i).toString();
        }// for(i)

        return pts;
    }// retrievePointsAsString()

    /**
     * saveEquation()
     * 
     * @param eqStr
     * @return boolean
     */
    public boolean saveEquation(final String eqStr) {
        // make sure equation string doesn't already exist in ntbk ArrayList
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                // equation already exists
                return false;
            }// if
        }// for(i)

        notebookEquations.add(new EquateNode(eqStr));

        // equation was deleted
        return true;
    }// saveEquation()

    /**
     * saveInterval()
     * 
     * @param eqStr
     * @param aPt
     * @param bPt
     * @return boolean
     */
    public boolean saveInterval(final String eqStr, final double aPt, final double bPt) {
        // TODO: test method
        EquateNode eq = null;

        // finding the corresonding EquateNode in ArrayList
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                eq = notebookEquations.get(i);
                break;
            }// if
        }// for(i)

        if (eq == null) {
            // eqStr does not exist
            return false;
        }// if(null)

        final ArrayList<IntervalNode> intrvls = eq.getIntervals();
        IntervalNode temp;

        // finding the corresonding IntervalNode in ArrayList
        for (int i = 0; i < intrvls.size(); i++) {
            temp = intrvls.get(i);
            if (aPt == temp.getA() && bPt == temp.getB()) {
                // interval already exists
                return false;
            }// if
        }// for(i)

        intrvls.add(new IntervalNode(aPt, bPt));

        // saved successfully
        return true;
    }// saveInterval()

    /**
     * savePoint()
     * 
     * @param eqStr
     * @param aPt
     * @param bPt
     * @param tanPt
     * @return boolean
     */
    public boolean savePoint(final String eqStr, final double aPt, final double bPt, final double tanPt) {
        // TODO: test method
        EquateNode eq = null;
        IntervalNode intnd = null;

        // finding the corresonding EquateNode in ArrayList
        for (int i = 0; i < notebookEquations.size(); i++) {
            if (eqStr.equals(notebookEquations.get(i).getEquation())) {
                eq = notebookEquations.get(i);
                break;
            }// if
        }// for(i)

        if (eq == null) {
            // eqStr does not exist
            return false;
        }// if(null)

        final ArrayList<IntervalNode> intrvls = eq.getIntervals();
        IntervalNode temp;

        // finding the corresonding IntervalNode in ArrayList
        for (int i = 0; i < intrvls.size(); i++) {
            temp = intrvls.get(i);
            if (aPt == temp.getA() && bPt == temp.getB()) {
                intnd = temp;
                break;
            }// if
        }// for(i)

        if (intnd == null) {
            // aPt and bPt do not exist
            return false;
        }// if(null)

        final ArrayList<Double> tanPts = intnd.getTanPts();

        for (int i = 0; i < tanPts.size(); i++) {
            if (tanPts.get(i).doubleValue() == tanPt) {
                // tangent point already exists
                return false;
            }// if
        }// for(i)

        tanPts.add(new Double(tanPt));

        // tangent point saved successfully
        return true;
    }// savePoint()
}
